package com.example.makerspace.manager;


import cn.hutool.crypto.digest.DigestUtil;
import com.example.makerspace.dao.UserDAO;
import com.example.makerspace.domain.UserDO;
import com.example.makerspace.dto.*;
import com.example.makerspace.enums.ResultCodeEnum;
import com.example.makerspace.enums.UserRoleEnum;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

import static com.example.makerspace.service.impl.AdminServiceImpl.managerMap;

@Component
public class UserManager extends BaseManager<UserDO, UserDTO>{

    private final static List<Map<String, String>> FUZZY_QUERY_PARAMS = Lists.newArrayList(
            ImmutableMap.<String, String>builder().put(QUERY_FIELD, "username").put(QUERY_TYPE, QUERY_TYPE_TERM).build(),
            ImmutableMap.<String, String>builder().put(QUERY_FIELD, "nickname").put(QUERY_TYPE, QUERY_TYPE_TERM).build()
    );

    @Resource
    private UserDAO userDAO;
    @Resource
    private ApplicationManager applicationManager;
    @Resource
    private ApplicationV2Manager applicationV2Manager;

    @PostConstruct
    public void init(){
        this.baseDAO = userDAO;
        managerMap.put("user", this);
    }
    public final static Map<String, UserRoleEnum> USER_ROLE_ENUM_MAP = ImmutableMap
            .<String, UserRoleEnum>builder()
            .put(UserRoleEnum.NORMAL.getRole(), UserRoleEnum.NORMAL)
            .put(UserRoleEnum.ADMIN.getRole(), UserRoleEnum.ADMIN)
            .put(UserRoleEnum.SUPER.getRole(), UserRoleEnum.SUPER)
            .build();

    public Result createUser(UserDO userDO) {
        String username = userDO.getUsername();
        UserDO oldUser = userDAO.selectByUsername(username);
        if(oldUser != null){
            return Result.error(ResultCodeEnum.USER_EXIST);
        }
        return addDO(userDO);
    }

    public Result delete(UserDTO userDTO) {
        UserDO userDO = userDAO.selectById(userDTO.getId());
        if(userDO == null){
            return Result.error(ResultCodeEnum.ID_NOT_EXIST);
        }
        userDAO.deleteById(userDTO.getId());
        applicationManager.deleteByUser(userDO);
        applicationV2Manager.deleteByUser(userDO);
        return Result.success();
    }

    public Result forgetPassword(RegistrationDTO registrationDTO) {
        String username = registrationDTO.getUsername();
        UserDO userDO = userDAO.selectByUsername(username);
        if(userDO == null){
            return Result.error(ResultCodeEnum.USER_NOT_EXIST);
        }
        String password = DigestUtil.sha256Hex(registrationDTO.getPassword());
        userDO.setPassword(password);
        boolean update = userDAO.updateById(userDO);
        return Result.success(ResultCodeEnum.CHANGE_PASSWORD_SUCCESS);
    }

    public Result updateUser(UserDTO userDTO, String role) {
        int id = userDTO.getId();
        UserDO userDO = userDAO.selectById(id);
        if(userDO == null){
            return Result.error(ResultCodeEnum.USER_NOT_EXIST);
        }
        if(userDO.getRole().equals(UserRoleEnum.SUPER.getRole()) && ! role.equals(UserRoleEnum.SUPER.getRole())){
            return Result.error(ResultCodeEnum.ONLY_SUPER);
        }
        AtomicReference<Result> result = new AtomicReference<>(Result.success());
        Optional.ofNullable(userDTO.getPassword()).ifPresent(userDO::setPassword);
        Optional.ofNullable(userDTO.getNickname()).ifPresent(userDO::setNickname);
        Optional.ofNullable(userDTO.getStatus()).ifPresent(userDO::setStatus);
        Optional.ofNullable(userDTO.getRole()).ifPresent(r ->{
            if(r.equals(UserRoleEnum.ADMIN.getRole()) || r.equals(UserRoleEnum.SUPER.getRole())){
                if(role.equals(UserRoleEnum.SUPER.getRole())){
                    userDO.setRole(r);
                }else {
                    result.set(Result.error(ResultCodeEnum.ONLY_SUPER));
                }
            }else{
                userDO.setRole(r);
            }
        });
        userDO.setModifyTime(new Date(System.currentTimeMillis()));
        userDAO.updateById(userDO);
        return result.get();
    }


    protected UserDTO convert2DTO(UserDO userDO){
        UserDTO userDTO = super.convert2DTO(userDO);
        userDTO.setRoleName(USER_ROLE_ENUM_MAP.get(userDO.getRole()).getRoleName());
//        if( userDTO.getRole().equals(UserRoleEnum.SUPER.getRole())){
//            userDTO.setPassword(null);
//        }
        userDTO.setPassword(null);
        StringBuilder mask = new StringBuilder();
        for (int i = 0; i < userDO.getPassword().length(); i++) {
            mask.append("*");
        }
        userDTO.setMask(mask.toString());
        return userDTO;
    }

    @Override
    public PageResult list(PageRequest pageRequest){
        Map<String, Object> params = pageRequest.getParams();
        Pagination pagination = pageRequest.getPagination();
        String fuzzy = MapUtils.getString(params, "fuzzy");
        PageResult result;
        if(StringUtils.isBlank(fuzzy)){
            result = super.list(pageRequest);
        }else {
            result = search(null, null, FUZZY_QUERY_PARAMS, fuzzy, pagination, UserDO.class);
        }
        return result;
    }
}
